#ifndef __BIN_TREE_H__
#define __BIN_TREE_H__

#include <functional>

template<typename T>
class BinTree
{
private:
	class BinTreeNode
	{
	private:
		BinTreeNode* left;
		BinTreeNode* right;
		T value;
		function<void(T&)> merger;

	public:
		BinTreeNode(T value, function<void(T&)> merger)
		{
			left = right = nullptr;
			this->value = value;
			this->merger = merger;
		}

		void insert(T in)
		{
			if(in->operator==(value))
			{
				merger(value);
			}
			else if(in->operator>(value))
			{
				if(right) right->insert(in);
				else right = new BinTreeNode(in, merger);
			}
			else
			{
				if(left) left->insert(in);
				else left = new BinTreeNode(in, merger);
			}
		}

		void for_each(function<void(T)> fn)
		{
			if(left) left->for_each(fn);
			fn(value);
			if(right) right->for_each(fn);
		}
	};

		BinTreeNode* root;
		function<void(T&)> merger;

	public:
		BinTree(function<void(T&)> merger)
		{
			root = nullptr;
			this->merger = merger;
		}

		void insert(T in)
		{
			if(root) root->insert(in);
			else root = new BinTreeNode(in, merger);
		}

		void for_each(function<void(T)> fn)
		{
			root->for_each(fn);
		}
	};

#endif